﻿<!DOCTYPE html>
<html>
<head>
<!--
  Copyright (c) 2015 Jean-Marc VIGLINO,
  released under CeCILL-B (french BSD like) licence: http://www.cecill.info/
-->
  <title>ol-ext: LayerShop</title>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

  <meta name="description" content="An OL3 layerswitcher." />
  <meta name="keywords" content="openlayers, ol, layer, layerswitcher, control" />

  <!-- jQuery -->
  <script type="text/javascript" src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
  <!-- FontAwesome -->
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">

  <!-- Openlayers -->
  <script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList,URL,Object.assign"></script>
  <link rel="stylesheet" href="https://openlayers.org/en/latest/css/ol.css" />
  <script type="text/javascript" src="https://openlayers.org/en/latest/build/ol.js"></script>
  
  <!-- ol-ext -->
  <link rel="stylesheet" href="../../dist/ol-ext.css" />
  <script type="text/javascript" src="../../dist/ol-ext.js"></script>
  <!-- Pointer events polyfill for old browsers, see https://caniuse.com/#feat=pointer -->
  <script src="https://unpkg.com/elm-pep"></script>

  <link rel="stylesheet" href="../style.css" />
  <style>
    .ol-layer-shop i {
      color: inherit;
      font-size: 1.3em;
    }
    textarea:focus, input:focus, select:focus {
      outline: none;
    }
    /* Remove opacity */
    .layerswitcher-opacity {
      display: none;
    }
    .ol-layer-shop .ol-bar input[type="number"] {
      width: 3em;
      height: 1em;
    }
  </style>
</head>
<body >
  <a href="https://github.com/Viglino/ol-ext" class="icss-github-corner"><i></i></a>

  <a href="../../index.html">
    <h1>ol-ext: LayerShop control</h1>
  </a>
  <div class="info">
    <b>ol/control/LayerShop</b> is a layer switcher integrating tool bars to handle layers properties.
  </div>

  <!-- Map div -->
  <div id="map" style="width: 100%; height: 400px;"></div>
  <div class="options">
  </div>
  
  <script type="text/javascript">

  // A group layer for base layers
  var baseLayers = new ol.layer.Group({
    title: 'Base Layers',
    openInLayerSwitcher: true,
    layers: [
      new ol.layer.Tile({
        title: "Watercolor",
        className: "Watercolor",
        baseLayer: true,
        source: new ol.source.Stamen({ layer: 'watercolor' })
      }),
      new ol.layer.Tile({
        title: "Toner",
        className: "Toner",
        baseLayer: true,
        visible: false,
        source: new ol.source.Stamen({ layer: 'toner' })
      }),
      new ol.layer.Tile({
        title: "OSM",
        className: "OSM",
        baseLayer: true,
        source: new ol.source.OSM(),
        visible: false
      })
    ]
  });
  var clc = new ol.layer.Tile ({
    title: 'CORINE Land Cover - France métropolitaine - 2018',
    className: 'CLC',
    extent: [
      -1099999.9999649636,
      4949999.999934867,
      1300000.000049673,
      6699999.999949973
    ],
    queryable: true,
    abstract: "Inventaire biophysique de l'occupation des sols en 2018 en 44 postes.",
    minResolution: 0.09449404761899723,
    maxResolution: 197231.79878968254,
    source: new ol.source.TileWMS({
      url: 'https://wxs.ign.fr/corinelandcover/geoportail/r/wms',
      projection: 'EPSG:3857',
      attributions: [],
      crossOrigin: 'anonymous',
      params: {
        LAYERS: 'LANDCOVER.CLC18_FR',
        FORMAT: 'image/png',
        VERSION: '1.3.0'
      }
    })
  });
  // The Map
  var map = new ol.Map({
    target: 'map',
    view: new ol.View({
      zoom: 11,
      center: [260497, 6249720]
    }),
    layers: [ 
      baseLayers, 
      new ol.layer.Geoportail({ 
        layer: 'GEOGRAPHICALGRIDSYSTEMS.PLANIGNV2', 
        className: 'PLANIGNV2',
        visible: false 
      }),
      new ol.layer.Geoportail({ 
        layer: 'ORTHOIMAGERY.ORTHOPHOTOS', 
        className: 'ORTHOPHOTOS' 
      }),
      new ol.layer.Geoportail({ 
        layer: 'CADASTRALPARCELS.PARCELLAIRE_EXPRESS',
        className: 'PARCELLAIRE_EXPRESS' 
      }),
      clc,
      new ol.layer.Tile({
        title: 'Labels',
        className: 'Labels',
        source: new ol.source.Stamen({ layer: 'terrain-labels' })
      }) 
    ]
  });

  // Add control inside the map
  var ctrl = new ol.control.LayerShop({
    minibar: true
  });
  map.addControl(ctrl);
  
  // WMS control
  var wms = new ol.control.WMSCapabilities({ 
    target: document.body,
    title: 'Add WMS',
    services: {
      'BRGM': 'https://geoservices.brgm.fr/geologie',
      'OSM': 'https://wms.openstreetmap.fr/wms',
      'OSM-Mundialis': 'https://ows.mundialis.de/services/service',
      'CorineLandCover': 'https://wxs.ign.fr/corinelandcover/geoportail/r/wms'
    },
    onselect: function(layer) {
      var index = map.getLayers().getArray().indexOf(ctrl.getSelection());
      map.getLayers().insertAt(index+1, layer);
      ctrl.selectLayer(layer);
    }
  });
  ctrl.addControl(wms, 'bottom');

  // Remove layer button
  ctrl.addControl(new ol.control.Button({
    html: '<i class="fa fa-trash-o"></i>',
    title: 'Remove layer',
    handleClick: function() {
      map.removeLayer(ctrl.getSelection());
    }
  }), 'bottom');
  
  // Info dialogue
  var dlg = new ol.control.Dialog({ closeBox: true, hideOnBack: true });
  map.addControl(dlg);
  // Show info
  ctrl.addControl(new ol.control.Button({
    html: '<i class="fa fa-info-circle"></i>',
    title: 'Information',
    handleClick: function() {
      var d = $('<div>');
      var layer = ctrl.getSelection();
      if (layer) {
        $('<h2>').text(layer.get('title')).appendTo(d);
        $('<p>').text(layer.get('desc') || layer.get('abstract')).appendTo(d);
        if (layer.getSource && layer.getSource()) {
          $('<div>').html(layer.getSource().getAttributions()().join('<br/>')).appendTo(d);
        }
        dlg.show(d.get(0));
      }
    }
  }), 'bottom');

  // Mix blend Menu
  var blendFilter = {
    multiply: new ol.filter.CSS({ blend: 'multiply' }),
    luminosity: new ol.filter.CSS({ blend: 'luminosity' }),
    color: new ol.filter.CSS({ blend: 'color' }),
    'color-burn': new ol.filter.CSS({ blend: 'color-burn' }),
    difference: new ol.filter.CSS({ blend: 'difference' }),
    overlay: new ol.filter.CSS({ blend: 'overlay' })
  };
  clc.addFilter(blendFilter.multiply);
  // Add selector
  var blend = ol.ext.element.create('SELECT', { 
    options: {
      'Mode' : '',
      'Multiply' : 'multiply',
      'Luminosity' : 'luminosity',
      'Color' : 'color',
      'Color burn' : 'color-burn',
      'Difference' : 'difference',
      'Overlay' : 'overlay'
    },
    on: {
      change: function(e) {
        for (var i in blendFilter) ctrl.getSelection().removeFilter(blendFilter[i]);
        if (blendFilter[blend.value]) ctrl.getSelection().addFilter(blendFilter[blend.value]);
      }
    },
    parent: ctrl.getBarElement()
  });
  // Update filter on select layer
  ctrl.on('select', function(e) {
    blend.value = '';
    for (var i in blendFilter) {
      if (ctrl.getSelection().getFilters().indexOf(blendFilter[i]) >= 0) blend.value = i;
    }
  });

  // Grayscale filter menu
  var filter = new ol.filter.Colorize('grayscale');
  filter.set('preserveAlpha', true);
  var sel = ol.ext.element.create('SELECT', { 
    options: {
      'Filter' : 'normal',
      'Grayscale' : 'grayscale'
    },
    on: {
      change: function() {
        if (ctrl.getSelection().getFilters().indexOf(filter) < 0) ctrl.getSelection().addFilter(filter);
        else ctrl.getSelection().removeFilter(filter);
      }
    },
    parent: ctrl.getBarElement()
  });
  // Update filter on select layer
  ctrl.on('select', function(e) {
    if (ctrl.getSelection().getFilters().indexOf(filter) < 0) sel.value = 'normal';
    else sel.value = 'grayscale';
  });

  // Opacity slider
  var opacity = new ol.ext.input.Slider({
    className: 'opacity',
    align: 'right',
    type: 'number',
    min: 0,
    max: 100,
    parent: ctrl.getBarElement()
  });
  opacity.on('change:value', function(e) {
    ctrl.getSelection().setOpacity(e.value/100);
  })
  ctrl.on(['layer:opacity', 'select'], function(e) {
    if (e.layer === ctrl.getSelection()) {
      opacity.setValue(Math.round(e.layer.getOpacity()*100));
    }
  });

  // Select first layer
  ctrl.selectLayer();
  </script>
  
</body>
</html>